﻿#include "study06.h"
// C/C++ 学习网站：https://legacy.cplusplus.com 注意旧版本（搜索）和新版本

/*
外部库导入本项目的步骤（以 GLFW 库为例）：
    1. 下载外部库源码（预编译二进制文件）或编译好的库文件（.lib或.dll文件），解压到指定目录。
    2. 在本项目的源文件夹目录（.sln文件所在目录）下新建一个文件夹，
        将外部库的头文件（.h 文件 一般在 include 文件夹里面）和库文件（.lib 文件 GLFW 中的 lib-vc2022 文件夹）复制到该文件夹。
        GLFW 库在 lib-vc2022 文件夹中可以看到 .lib 和.dll 文件，
        .dll 文件中包含了外部库文件的函数实现；.lib 文件中包含了 .dll 文件的导出符号（函数名等）;
        较大的 .dll 文件属于静态库（比如 glfw3.dll），较小的 .lib 文件属于动态库（功能可以选择）。
        GLFW 库的 .h 文件在 include 文件夹中。
    3. 在本项目的源文件中，包含外部依赖项和引入外部库的头文件：
        首先，右键项目名称，选择属性，在 C/C++ 常规选项卡中，添加附加包含目录的值为：$(SolutionDir) 宏
        表示当前解决方案文件（.sln文件）所在目录，常用的这种宏还有 $(ProjectDir) $(OutDir) $(TargetDir) $(InputDir) $(RootDir)
        然后再将之后的目录（.h 文件所在目录）加上（注意选择配置与平台）：
            我这里完整的目录为：$(SolutionDir)packages\GLFW\include\

        其次，右键项目名称，选择属性，在 链接器->常规 选项卡中，添加附加依赖目录的值为：$(SolutionDir) 宏
        然后再将之后的目录（.lib 文件所在目录）加上（注意选择配置与平台）：
            我这里完整的目录为：$(SolutionDir)packages\GLFW\lib-vc2022
        这里还需要添加附加依耐项（.lib 文件）：在 链接器->输入 选项卡中，添加比如 glfw3.lib 依赖项（多个依赖项用 ; 隔开）
        我添加了两个依耐项：glfw3.lib (静态库) 和 glfw3dll.lib（动态库）；
        完全使用 OpenGL 构建窗口时可以添加依赖项 opengl32.lib、glfw3.lib、gdi32.lib、user32.lib、shell32.lib、advapi32.lib。
    这里最主要的 opengl32.lib 是为了解决无法解析的外部符号 _imp_glClear 错误；而 user32.lib 是提供 windows 接口之类（包含了 Library 库）的需要；gdi32.lib 用于创建设备上下文和交换缓冲；shell32.lib 用于创建窗口，查询文件。
        添加了动态库依耐项后，需要将对应的 .dll 文件复制到运行目录（Debug 或 Release）下，
        我这里是：$(OutDir) 宏，所以复制到 Debug 文件夹下(Debug 或 Release 文件夹下)；这个步骤需要手动去项目目录文件夹下完成。
    4. 在源文件中，引入外部库的头文件（上面目录中的 .h 头文件）如下写法：
        #include "glfw3.h"   // 当然也可以用 #include <glfw3.h> 因为是自己添加的包含目录
        说明：编译器在查找头文件时 "" 会优先包含当前目录（自己的源代码 .cpp 文件所在目录）下的头文件，找不到再去系统默认的库目录下找；
        而 <> 只会包含系统默认的库目录下的头文件（自己添加的附加包含目录也算）。
最后说明一点：引入静态库，最终生成的可执行文件（.exe 文件）不再需要依赖外部库的 .lib 文件，
    也就是可以放在任何文件夹下运行，不过具体需看实现的库的依耐。但是动态库需要依耐的 .dll 文件
*/

#define WINDOW_WITH     800
#define WINDOW_HEIGHT   800

static void renderCircle() {
    glBegin(GL_TRIANGLE_FAN);
    glColor3f(0.8f, 0.3f, 0.8f); // 粉色中心
    glVertex2f(0.0f, 0.0f);

    float perimeter = 2.0f * 3.14159265f;
    for (float angle = 0.0f; angle <= perimeter; angle += 0.001f) {
        float x = 0.5f * cosf(angle);
        float y = 0.5f * sinf(angle);
        glColor3f(x + 0.5f, y + 0.5f, 0.5f); // 渐变色
        glVertex2f(x, y);
    }
    glEnd();
}

//void DrawCircle(float x, float y, float radius, int segments) {
//    glBegin(GL_TRIANGLE_FAN);
//    glVertex2f(x, y); // 圆心
//    for (int i = 0; i <= segments; ++i) {
//        float angle = 2.0f * 3.1415926f * float(i) / float(segments);
//        float px = x + radius * cosf(angle);
//        float py = y + radius * sinf(angle);
//        glVertex2f(px, py);
//    }
//    glEnd();
//}

int main()
{
    using std::cout;
    using std::endl;
    cout << "Hello World!" << endl;

    cout << "2.5 + 3.6 = " << self_lib::add(2.5f, 3.6f) << endl; // 调用自己创建的库的函数

    int a = glfwInit();
    if (a == GLFW_FALSE)
    {
        cout << "GLFW initialization failed!" << endl;
        return -1;
    }

    cout << "in GLFW library, glfwInit() return a = " << a << endl;

    //glfwWindowHint(GLFW_SAMPLES, 2); // 启用 2 倍多采样

    // glfw create window
    // 创建一个窗口
    GLFWwindow* window = glfwCreateWindow(WINDOW_WITH, WINDOW_HEIGHT, "Hello GLFW", nullptr, nullptr);
    if (!window)
    {
        std::cerr << "Failed to create GLFW window" << endl;
        glfwTerminate();
        return -1;
    }

    // 设置当前上下文
    glfwMakeContextCurrent(window);

    // 设置视口
    glViewport(0, 0, WINDOW_WITH, WINDOW_HEIGHT);

    // 设置二维正射投影
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);

    // 主循环
    while (!glfwWindowShouldClose(window))
    {
        // 渲染代码可以放在这里
        // 清除颜色缓冲
        glClear(GL_COLOR_BUFFER_BIT);

        // 渲染圆形
        renderCircle();
        //DrawCircle(WINDOW_WITH / 2, WINDOW_HEIGHT / 2, 0.5f, 36);

        // 交换前缓冲和后缓冲
        glfwSwapBuffers(window);

        // 检查并调用事件处理函数
        glfwPollEvents();
    }

    // 清理 GLFW 资源
    glfwDestroyWindow(window);
    glfwTerminate();

    system("pause");
    return 0;
}
